package com.ailot.cloud.base.security.utils;


import cn.hutool.json.JSONUtil;
import com.ailot.cloud.base.security.model.JwtUser;
import com.nimbusds.jose.shaded.json.JSONArray;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
import org.springframework.security.oauth2.jwt.JwtEncoderParameters;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.GZIPOutputStream;

import static com.ailot.cloud.base.common.constants.SecurityConstant.*;


@Slf4j
@UtilityClass
public class JWTUtil {


    private final static String ISSUER = "AILOT";


    private static Long expire = 24L;

    @Value("${jwt.expire}")
    public static void setExpire(Long expire) {
        JWTUtil.expire = expire;
    }

    /**
     * 通过认证信息返回 jwt数据
     */
    public static JwtEncoderParameters authenticationToJwtParameters(JwtUser jwtUser) {

        Instant now = Instant.now();

        String userStr = JSONUtil.toJsonStr(jwtUser);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        // 手动压缩 gzip
        try (GZIPOutputStream gzip = new GZIPOutputStream(bos)) {

            gzip.write(userStr.getBytes(StandardCharsets.UTF_8));
        } catch (IOException exception) {
            log.error("编码异常");
        }
        byte[] compressed = bos.toByteArray();

//        Collection<GrantedAuthority> authorities = jwtUser.getAuthorities();
        List<GrantedAuthority> list = jwtUser.getAuthorities().stream().collect(Collectors.toList());
        List<String> stringList = list.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());

        // 构造一致的 jwt
        JwtClaimsSet claims = JwtClaimsSet.builder()
                .issuer(ISSUER)
                .issuedAt(now)
                .expiresAt(now.plus(Duration.ofHours(expire)))
                .subject(jwtUser.getUsername())
                // 认证用户信息
                .claim(ID, jwtUser.getId())
                .claim(ORGID, jwtUser.getOrgId())
                .claim(USERNAME, jwtUser.getUsername())
                .claim(AUTHORITIES, stringList)
                .build();

        return JwtEncoderParameters.from(claims);
    }

    public static JwtUser principalFrom(Jwt jwt) {
        //从jwt中恢复用户信息和权限
        String id = jwt.getClaim(ID);
        String orgId = jwt.getClaim(ORGID);
        String username = jwt.getClaim(USERNAME);
        // 由于jwtdecode出来集合为jsonArray，这里需要手动转换
        JSONArray jsonArray = jwt.getClaim(AUTHORITIES);
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>(jsonArray.size());
        jsonArray.forEach(item -> {
            grantedAuthorities.add(new SimpleGrantedAuthority((String) item));
        });
        JwtUser jwtUser = new JwtUser(id, orgId, username, "", grantedAuthorities);
        return jwtUser;

    }
}
